/*
 * =====================================================================================
 *
 *       Filename:  signal2.hpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  09.07.2012 14:29:37
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  YOUR NAME (), 
 *   Organization:  
 *
 * =====================================================================================
 */

#ifndef SIGNAL2_HPP_
#define SIGNAL2_HPP_

#include <functional>
#include <utility>

namespace Drosera {

template<typename R, typename... Args>
class Signal2 {

	public:
		
		/*
		 * Default constructor for creating a Signal2
		 * 1) Empty Signal2
		 * 2) Signal2 with function
		 */

		Signal2 ( void ) {
		}

		Signal2 ( std::function<R (Args...)>& sig ) {
			m_sig = sig;
		}
		
		Signal2 ( const std::function<R (Args...)>& sig ) {
			m_sig = sig;
		}

		Signal2 ( std::function<R (Args...)>&& sig ) {
			m_sig = std::move ( sig );
		}


		/*
		 * Default copy-constructors for the Signal2s
		 * 1) rvalue reference copy constructor
		 * 2) normal reference constructor
		 * 3) same as above
		 * 4) pass an function Pointer
		 */

		Signal2 ( Signal2 && sig ) {
			m_sig = std::move ( sig.getSignal2() );
		}
		
		Signal2 ( Signal2 &sig ) {
			m_sig = sig.getSignal2();
		}

		Signal2 ( const Signal2 &sig ) {
			m_sig = sig.getSignal2();
		}


		/*
		 * Default destructor - nothing to do
		 */
		virtual ~Signal2( void ) {};

		void operator= ( const Signal2 &sig ) {
			m_sig = sig.getSignal2();
		}

		void operator= ( Signal2 &sig ) {
			m_sig = sig.getSignal2();
		}

		void operator= ( Signal2 &&sig ) {
			m_sig = std::move ( sig.getSignal2() );
		}

		/*
		 * Execute all functions with arguments
		 */

		R operator() ( Args... args ) {
			m_sig( args... );
		}


		/*
		 * Connecting a new function to the Signal2
		 */

		void connect ( const std::function<R (Args...)> &sig ) {
			m_sig = sig ;
		}

		void connect ( std::function<R (Args...)>& sig ) {
			m_sig = sig ;
		}

		void connect ( std::function<R (Args...)>&& sig ) {
			m_sig = std::move ( sig );
		}


		/*
		 * Return the signal as a function
		 */

		const std::function<R (Args...)>& getSignal2 ( void ) const {
			return m_sig;
		}

	private:
		std::function<R (Args...)> m_sig;
	protected:

};
template<typename R>
class Signal2<R> {

	public:
		
		/*
		 * Default constructor for creating a Signal2
		 * 1) Empty Signal2
		 * 2) Signal2 with function
		 */

		Signal2 ( void ) {
		}

		Signal2 ( std::function<R ()>& sig ) {
			m_sig = sig;
		}
		
		Signal2 ( const std::function<R ()>& sig ) {
			m_sig = sig;
		}

		Signal2 ( std::function<R ()>&& sig ) {
			m_sig = std::move ( sig );
		}


		/*
		 * Default copy-constructors for the Signal2s
		 * 1) rvalue reference copy constructor
		 * 2) normal reference constructor
		 * 3) same as above
		 * 4) pass an function Pointer
		 */

		Signal2 ( Signal2 && sig ) {
			m_sig = std::move ( sig.getSignal2() );
		}
		
		Signal2 ( Signal2 &sig ) {
			m_sig = sig.getSignal2();
		}

		Signal2 ( const Signal2 &sig ) {
			m_sig = sig.getSignal2();
		}


		/*
		 * Default destructor - nothing to do
		 */
		virtual ~Signal2( void ) {};

		void operator= ( const Signal2 &sig ) {
			m_sig = sig.getSignal2();
		}

		void operator= ( Signal2 &sig ) {
			m_sig = sig.getSignal2();
		}

		void operator= ( Signal2 &&sig ) {
			m_sig = std::move ( sig.getSignal2() );
		}

		/*
		 * Execute all functions with arguments
		 */

		R operator() ( void ) {
			m_sig();
		}


		/*
		 * Connecting a new function to the Signal2
		 */

		void connect ( const std::function<R ()> &sig ) {
			m_sig = sig ;
		}

		void connect ( std::function<R ()>& sig ) {
			m_sig = sig ;
		}

		void connect ( std::function<R ()>&& sig ) {
			m_sig = std::move ( sig );
		}


		/*
		 * Return the signal as a function
		 */

		const std::function<R ()>& getSignal2 ( void ) const {
			return m_sig;
		}

	private:
		std::function<R ()> m_sig;
	protected:

};

#endif
